﻿#pragma once
/**@author 由W意波(LuoJun)编写*/
#define LK_PROPERTY_
#include <stddef.h>
namespace LK {
	//编译器扩展的属性支持
#ifdef _VC
	/**
	@brief 只读属性
	@warning 目前只有Visual Studio支持属性*/
#define PROPERTY_Get(Name,GetFunction)\
		__declspec(property(get=GetFunction)) Name
	/**
	@brief 只写属性
	@warning 目前只有Visual Studio支持属性*/
#define PROPERTY_Set(Name,SetFunction)\
		__declspec(property(put=SetFunction)) Name
	/**
	@brief 读写属性
	@warning 目前只有Visual Studio支持属性*/
#define PROPERTY_GetSet(Name,GetFunction,SetFunction)\
		__declspec( property( get=GetFunction, put=SetFunction ) ) Name

#else
#define PROPERTY_Get(Name,GetFunction)
#define PROPERTY_Set(Name,SetFunction)
#define PROPERTY_GetSet(Name,GetFunction,SetFunction)
#endif


	/**@brief 读写属性(已过时，不用)*/
	template<class T, class ObjectT>struct Property
	{
	private:
		ObjectT& This;//具体实例指针
		T(ObjectT::*getMethod)(void)const;//保存get方法函数指针
		void (ObjectT::*setMethod)(T);//保存set方法函数指针
	public:
		Property(ObjectT& pCurrent, T(ObjectT::*method_get)(void)const, void(ObjectT::*method_set)(T)) :getMethod(method_get), setMethod(method_set), This(pCurrent) {}
		inline operator T()const { return (This.*getMethod)(); }//取方法
		inline Property& operator=(T t)const { (This.*setMethod)(t); return const_cast<Property&>(*this); }//写前执行的方法
	};
	/**@brief 只读属性(已过时，不用)*/
	template<class T, class ObjectT>struct PropertyReadOnly
	{
	private:
		ObjectT& This;//具体实例指针
		T(ObjectT::*getMethod)(void)const;//保存get方法函数指针
	public:
		PropertyReadOnly(ObjectT& pCurrent, T(ObjectT::*method_get)(void)const) :getMethod(method_get), This(pCurrent) {}
		inline operator T()const { return (This.*getMethod)(); }//取方法
	};
	/**brief 只写属性(已过时，不用)*/
	template<class T, class ObjectT>struct PropertyWriteOnly
	{
	private:
		ObjectT& This;//具体实例指针
		void (ObjectT::*setMethod)(T);//保存set方法函数指针
	public:
		PropertyWriteOnly(ObjectT& pCurrent, void(ObjectT::*method_set)(T)) :setMethod(method_set), This(pCurrent) {}
		PropertyWriteOnly& operator=(T t) { (This.*setMethod)(t); return *this; }//写前执行的方法
	};
	/**@brief 静态的读写属性*/
	template<class T>struct StaticProperty//T类型属性，指定get方法和set方法
	{
	private:
		T(&getMethod)(void);//保存get方法函数
		void(&setMethod)(const T&);//保存set方法函数
	public:
		StaticProperty(T(&method_get)(void), void(&method_set)(const T&)) :getMethod(method_get), setMethod(method_set) {}
		inline operator T()const { return (getMethod)(); }//取方法
		inline StaticProperty& operator=(const T&t)const { (setMethod)(t); return const_cast<StaticProperty&>(*this); }//写方法
	};
	/**@brief 静态的只读属性*/
	template<class T>struct StaticPropertyReadOnly
	{
	private:
		T(&getMethod)(void);//保存get方法函数
	public:
		StaticPropertyReadOnly(T(&method_get)(void)) :getMethod(method_get) {}
		operator T()const { return (getMethod)(); }//取方法
	};

	//以下属性的实现方法从Imperfect C++中得来，在Debug模式和非/clr编译下,VS2010及以前有可能会导致编译器内部错误，

	typedef ptrdiff_t(*PFnOff)();

	template<typename V, typename C, void (C::*PFnSet)(V), PFnOff off>
	struct property_set
	{
		inline const property_set& operator=(V v)const
		{
			(((C*)((unsigned char*)this - (*off)()))->*PFnSet)(v);
			return *this;
		}
	};
	template<typename R, typename C, R(C::*PFnGet)(void)const, PFnOff off>

	struct property_get
	{
		operator R()const
		{
			return (((C*)((unsigned char*)this - (*off)()))->*PFnGet)();
		}
	};

	template<typename V, typename C, V(C::*PFnGet)()const, void (C::*PFnSet)(V), PFnOff off>
	struct property_getset
	{
		inline operator V()const
		{
			return (((C*)((unsigned char*)this - (*off)()))->*PFnGet)();
		}
		inline const property_getset& operator=(V v)const
		{
			(((C*)((unsigned char*)this - (*off)()))->*PFnSet)(v);
			return *this;
		}
	};

	template<typename V, typename C, V& (C::*PFnGetSet)(), PFnOff off>
	struct property_ref
	{
		inline operator V()const
		{
			return (((C*)((unsigned char*)this - (*off)()))->*PFnGetSet)();
		}
		inline const property_ref& operator=(V v)const
		{
			(((C*)((unsigned char*)this - (*off)()))->*PFnGetSet)() = v;
			return *this;
		}
	};

	//以下为代理类对象专用属性，传入的get、set方法均在代理类中
	template<typename V, typename C, void (C::*PFnSet)(V), const size_t __PtMov>
	struct xproperty_set
	{
		inline const xproperty_set& operator=(V v)const
		{
			(((C*)((BYTE*)this + __PtMov))->*PFnSet)(v);
			return *this;
		}
	};
	template<typename V, typename C, void (C::*PFnSet)(V const&), const size_t __PtMov>//特化版本:set const&
	struct xproperty_setr
	{
		inline const xproperty_setr& operator=(V const& v)const
		{
			(((C*)((BYTE*)this + __PtMov))->*PFnSet)(v);
			return *this;
		}
	};
	template<typename R, typename C, R(C::*PFnGet)(void)const, const size_t __PtMov>
	struct xproperty_get
	{
		inline operator R()const
		{
			return (((C*)((BYTE*)this + __PtMov))->*PFnGet)();
		}
	};
	template<typename V, typename C, V(C::*PFnGet)()const, void (C::*PFnSet)(V), const size_t __PtMov>
	struct xproperty_getset
	{
		inline operator V()const { return (((C*)((BYTE*)this + __PtMov))->*PFnGet)(); }
		inline const xproperty_getset& operator=(V v)const { (((C*)((BYTE*)this + __PtMov))->*PFnSet)(v); return *this; }
	};
	template<typename V, typename C, V(C::*PFnGet)()const, void (C::*PFnSet)(V const&), const size_t __PtMov>//特化版本:set const&
	struct xproperty_getsetr
	{
		inline operator V()const { return (((C*)((BYTE*)this + __PtMov))->*PFnGet)(); }
		inline const xproperty_getsetr& operator=(V const& v)const { (((C*)((BYTE*)this + __PtMov))->*PFnSet)(v); return *this; }
	};
	template<typename V, typename C, V& (C::*PFnGetSet)(), const size_t __PtMov>
	struct xproperty_ref
	{
		inline operator V&()const { return (((C*)((BYTE*)this + __PtMov))->*PFnGetSet)(); }
		inline const xproperty_ref& operator=(V v)const { (((C*)((BYTE*)this + __PtMov))->*PFnGetSet)() = v; return *this; }
		template<class T>inline const xproperty_ref& operator+=(T const& v)const { ((V&)*this) += v; return *this; }
		template<class T>inline const xproperty_ref& operator-=(T const& v)const { ((V&)*this) -= v; return *this; }
		template<class T>inline const xproperty_ref& operator*=(T const& v)const { ((V&)*this) *= v; return *this; }
		template<class T>inline const xproperty_ref& operator/=(T const& v)const { ((V&)*this) /= v; return *this; }
		template<class T>inline const xproperty_ref& operator%=(T const& v)const { ((V&)*this) %= v; return *this; }
		inline V* operator&() { return &(V&)(((C*)((BYTE*)this + __PtMov))->*PFnGetSet)(); }
		inline V const* operator&()const { return &(V&)(((C*)((BYTE*)this + __PtMov))->*PFnGetSet)(); }
	};
}